﻿//using UnityEngine;
using System.Collections;
using System;
/// <summary>
/// xiao hong 704872627   讨论群 152767675
/// </summary>
using System.Collections.Generic;

namespace FrameWork
{
    public class UIManager : Singleton<UIManager>
    {
       public class UIInfoData
        {
           //不需要外部设置值 防止类外部赋值
            public EnumUIType UIType
            {
                get;private set;
            }
           //资源路径
            public string Path { get; private set; }
            
           public Type ScriptType
            {

                get;
                private set;
            }

           //参数。。可变参数
            public object[] UIparams { get; private set; }

            public UIInfoData(EnumUIType _uiType, string _path, params object[] _uiParams)
            {
                UIType = _uiType;
                Path = _path;
                UIparams = _uiParams;
                this.ScriptType = UIPathDefines.GetUIScriptByType(this.UIType);
            }
        }

        /// <summary>
        /// 已经打开UI集合 字典类型
        /// </summary>
        private Dictionary<EnumUIType, UnityEngine.GameObject> dicOpenUIs = null;

        /// <summary>
        /// 需要打开的UI
        /// </summary>
        private Stack<EnumUIType> stackOpenUIs = null;

        private Stack<UIInfoData>stackOpenUIs11 = null;

        public override void Init()
        {
            base.Init();
            dicOpenUIs = new Dictionary<EnumUIType, UnityEngine.GameObject>();
            stackOpenUIs = new Stack<EnumUIType>();
            stackOpenUIs11 = new Stack<UIInfoData>();
        }

        //获取指定UI 条件约束
        /// <summary>
        /// 获取UI组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_uiType"></param>
        /// <returns></returns>
        public T GetUI<T>(EnumUIType _uiType) where T :BaseUI
        {
            UnityEngine.GameObject _retObj = GetUIObject(_uiType);
            if(_retObj != null)
            {
                return _retObj.GetComponent<T>();
            }
            return null;
        }

        /// <summary>
        /// 获取缓存中指定UI的GameObject
        /// </summary>
        /// <param name="_uiType"></param>
        /// <returns></returns>
        public UnityEngine.GameObject GetUIObject(EnumUIType _uiType)
        {
            UnityEngine.GameObject _retObj = null;
            if (!dicOpenUIs.TryGetValue(_uiType, out _retObj))
                throw new SingleException("DicOpenUIs TryGetValue failure!!");
            return _retObj;
        }

        //预加载单个资源
        public void PreloadUI(EnumUIType _uiType)
        {
            string _path = UIPathDefines.GetPrefabsPathByType(_uiType);
            UnityEngine.Resources.Load(_path);
        }

        //预加载多个资源
        public void PreloadUI(EnumUIType[] _uiTypes)
        {
            for (int i = 0; i < _uiTypes.Length;i++ )
            {
                PreloadUI(_uiTypes[i]);
            }
        }

        public void OpenUI(EnumUIType _uiType)
        {
           // UnityEngine.Debug.LogError("public void OpenUI(EnumUIType _uiType)");
            EnumUIType[] _uiTypes = new EnumUIType[1];
            _uiTypes[0] = _uiType;
            OpenUI(_uiTypes);
            
        }

        //uitypes 打开UI
        public void OpenUI(EnumUIType[] _uiTypes)
        {
            OpenUI(false, _uiTypes, null);
        }

       //单个uitype打开UI
        public void OpenUI(EnumUIType _uiType,params object[] _uiParams)
        {
            EnumUIType[] _uiTypes = new EnumUIType[1];
            _uiTypes[0] = _uiType;
            OpenUI(false, _uiTypes, _uiParams);
        }

        //数组types打开UI、关闭其他
        public void OpenUICloseOthers(EnumUIType[] _uiTypes)
        {
            OpenUI(true, _uiTypes, null);

        }

        //单个type打开UI、关闭其他
        public void OpenUICloseOthers(EnumUIType _uiType,params object[] _uiParams)
        {
            EnumUIType[] _uiTypes = new EnumUIType[1];
            _uiTypes[0] = _uiType;
            OpenUI(true, _uiTypes, _uiParams);
        }

        /// <summary>
        /// 打开UI
        /// </summary>
        /// <param name="_isCloseOthers"></param>
        /// <param name="_uiTypes"></param>
        /// <param name="_uiParams"></param>
        public void OpenUI(bool _isCloseOthers,EnumUIType[] _uiTypes,params object[] _uiParams)
        {
            if (_isCloseOthers)
            {
                CloseUIAll();
            }

            //push ui types in stack
            //把将要打开的UI放在缓存的堆栈中
            for (int i = 0; i < _uiTypes.Length;i++ )
            {
                EnumUIType _uiType = _uiTypes[i];

                //是否存在键值
                if (!dicOpenUIs.ContainsKey(_uiType))
                {
                    string _path = UIPathDefines.GetPrefabsPathByType(_uiType);

                    //放在堆栈里去
                    stackOpenUIs11.Push(new UIInfoData(_uiType, _path, _uiParams));
                }
               
            }


            //UI同步或者异步加载(协程)
            if (stackOpenUIs11.Count > 0)
            {
                CoroutineController.Instance.StartCoroutine(AsyncLoadData());
            }

        }

        //UI加载------协程异步加载（resManger资源加载）
        private IEnumerator<int> AsyncLoadData()
        {
            UIInfoData _uiInfoData = null;

            //对象保存
            UnityEngine.Object _prefab = null;
            UnityEngine.GameObject _uiObj = null; 
            if (stackOpenUIs11 != null && stackOpenUIs11.Count > 0)
            {
                do 
                {
                    //堆栈中POP一个出来
                    _uiInfoData = stackOpenUIs11.Pop();
                    _prefab = UnityEngine.Resources.Load(_uiInfoData.Path);
                    if (null != _prefab)
                    {
                        _uiObj = UnityEngine.MonoBehaviour.Instantiate(_prefab) as UnityEngine.GameObject;
                        BaseUI _baseUI = _uiObj.GetComponent<BaseUI>();
                        
                        //UI脚本 如果没有挂脚本组件，则加上组件
                        if (null == _baseUI)
                        {
                            _baseUI = _uiObj.AddComponent(_uiInfoData.ScriptType) as BaseUI;
                        }
                        if (null != _baseUI)
                        {
                            //参数的传递
                            _baseUI.SetUIWhenOpening(_uiInfoData.UIparams);
                        }
                        dicOpenUIs.Add(_uiInfoData.UIType, _uiObj);
                    }
                } while (stackOpenUIs11.Count >0);
            }

            yield return 0;
        }

        //全部UI关闭
        public void CloseUIAll()
        {
            //取键值
            List<EnumUIType> _listKey = new List<EnumUIType>(dicOpenUIs.Keys);

            //CloseUI(_listKey.ToArray());

            for (int i = 0; i < _listKey.Count;i++ )
            {
                CloseUI(_listKey[i]);
            }
            //清空缓冲融洽
            dicOpenUIs.Clear();
        }

        //关闭多个指定UI
        public void CloseUI(EnumUIType[] _uiTypes)
        {
            for (int i = 0; i < _uiTypes.Length;i++ )
            {
                CloseUI(_uiTypes[i]);
            }
        }

        //关闭UI响应事件
        private void CloseUIHandle(Object obj, EnumObjectState newState, EnumObjectState oldState)
        {
            if (newState == EnumObjectState.Closeing)
            {
                BaseUI _baseUI = obj as BaseUI;
                dicOpenUIs.Remove(_baseUI.GetUIType());

                //委托事件移除掉
                _baseUI.StateChangeed -= CloseUIHandle;
            }
        }

        public void CloseUI(EnumUIType _uiType)
        {
            UnityEngine.GameObject _uiObj = GetUIObject(_uiType);
            if (null == _uiObj)
            {
                //在缓冲中删除
                dicOpenUIs.Remove(_uiType);
            }
            else
            {
                BaseUI _baseUI = _uiObj.GetComponent<BaseUI>();
                if (null == _baseUI)
                {
                    //移除掉
                    UnityEngine.GameObject.Destroy(_uiObj);
                    dicOpenUIs.Remove(_uiType);
                }
                else
                {
                    //委托事件而已
                    _baseUI.StateChangeed += CloseUIHandle;
                    _baseUI.Release();
                }
            }
        }

    }
}
